package main

import (
	"fmt"
	"strconv"
)

type Calculator struct {
	Stack
}

func (this *Calculator) IsOper(val int) bool {
	if val == 42 || val == 43 || val == 45 || val == 47 {
		return true
	}
	return false
}

func (this *Calculator) Cal(num2 int, oper int, num1 int) int {
	res := 0
	switch oper {
	case 42:
		res = num2 * num1
	case 43:
		res = num2 + num1
	case 45:
		res = num2 - num1
	case 47:
		res = num2 / num1
	default:
		fmt.Println("运算符有误")
	}
	return res
}

func (this *Calculator) Priority(oper int) int {
	if oper == 42 || oper == 47 {
		return 1
	} else if oper == 43 || oper == 45 {
		return 0
	}
	return 0
}

func Calc() {
	numStack := &Calculator{
		Stack{
			MaxTop: 20,
			Top:    -1,
		},
	}
	operaStack := &Calculator{
		Stack{
			MaxTop: 20,
			Top:    -1,
		},
	}
	expr := "30+4*20-1"
	index := 0
	num1 := 0
	num2 := 0
	res := 0
	keepNum := ""
	for {
		ch := expr[index : index+1]
		temp := int([]byte(ch)[0])
		if operaStack.IsOper(temp) { //运算符
			if operaStack.Top == -1 {
				operaStack.Push(temp)
			} else if operaStack.Priority(temp) <
				operaStack.Priority(operaStack.arr[operaStack.Top]) {
				num1 = numStack.Pop()
				num2 = numStack.Pop()
				operator := operaStack.Pop()
				res = numStack.Cal(num2, operator, num1)
				numStack.Push(res)
				operaStack.Push(temp)
			} else if operaStack.Priority(temp) >=
				operaStack.Priority(operaStack.arr[operaStack.Top]) {
				operaStack.Push(temp)
			}
		} else { //数字
			keepNum +=ch
			if index == len(expr)-1 {
				i, _ := strconv.Atoi(string([]byte{byte(temp)})[:1])
				numStack.Push(i)
			} else if operaStack.IsOper(int([]byte(expr[index+1 : index+2])[0])) {
				i, _ := strconv.ParseInt(keepNum, 10, 64)
				numStack.Push(int(i))
				keepNum = ""
			}
		}
		if index == len(expr)-1 {
			break
		}
		index++
	}
	for {
		if numStack.Top == 0 {
			break
		}
		num1 = numStack.Pop()
		num2 = numStack.Pop()
		res = numStack.Cal(num2, operaStack.Pop(), num1)
		numStack.Push(res)
	}

	fmt.Println("num =", numStack.Pop())
}
